<template>
  <div>
    <div class="new-page" :style="{ height: height + 'px' }">
      <el-row :gutter="20">
        <el-col :span="isConfigArea ? 24 : 18">
          <div ref="gantt" :style="{ height: height + 'px' }" />
        </el-col>
        <el-col v-if="!isConfigArea" :span="isConfigArea ? 0 : 6">
          <el-card>
            <el-tabs v-model="activeName">
              <el-tab-pane name="first"
                ><span class="tabClass" slot="label"><i class="el-icon-date"></i> 任务信息</span>
                <taskConfig
                  :height="height"
                  :taskInfoDate="taskInfoDate"
                  @refreshTask="refreshTask"
                  @openTaskDetail="openTaskDetail"
                  @cancel="closeInfo"
                ></taskConfig>
              </el-tab-pane>
              <el-tab-pane name="second"
                ><span class="tabClass" slot="label"><i class="el-icon-date"></i> 参数配置</span>
                <totalConfig
                  :height="height"
                  :configData="configData"
                  @updateGantt="updateGantt"
                  @cancel="closeInfo"
                ></totalConfig>
              </el-tab-pane>
            </el-tabs>
          </el-card>
        </el-col>
      </el-row>
    </div>
  </div>
</template>
  <script>
import gantt from "dhtmlx-gantt"; // 引入模块
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
import taskConfig from "./taskConfig.vue";
import totalConfig from "./totalConfig.vue";

export default {
  name: "DhtmlxGantt",
  props: {
    height: {
      type: String,
      default: "640",
    },
    isShowGrid: {
      type: Boolean,
      default: true,
    },
    isFullScreen: {
      type: Boolean,
      default: true,
    },
    ganttCondition: {
      type: Object,
      default: () => {},
    },
  },
  inject: ["microservices", "resource", "busSource"],
  components: {
    taskConfig,
    totalConfig,
  },
  data() {
    return {
      titlelist: [
        {
          name: "title",
          label: "任务名称",
          min_width: 240,
          resize: true,
          tree: true,
        },
        {
          name: "state",
          label: "任务状态",
          align: "center",
          sort: true,
          resize: true,
        },
        {
          name: "level",
          label: "优先级",
          align: "center",
          resize: true,
          template: function (task) {
            let className = "";
            if (task.level == "低") {
              className = "level level-success";
            } else if (task.level == "中") {
              className = "level level-primary";
            } else if (task.level == "高") {
              className = "level level-warning";
            } else if (task.level == "紧急") {
              className = "level level-danger";
            }
            return `<div class='${className}'>${task.level}</div>`;
          },
        },
        {
          name: "responsibleName",
          label: "负责人",
          align: "center",
          resize: true,
        },
        {
          name: "add",
          max_width: "40",
        },
      ],
      isConfigArea: true,
      activeName: "first",
      tasks: {
        data: [],
        links: [],
      },
      taskInfoDate: {},
      configData: {
        btnHeight: 38,
        rowHeight: 40,
        scaleHeight: 50,
        scrollOffset: 110,
        workTime: "day",
        isFullScree: "0",
        blockBorderColor: "#e3e4e6",
        exportFileType: "EXCEL",
        readonly: false,
        isDragProgress: true,
        isDragLink: true,
        isDragMove: true,
        isDragSort: true,
        showLink: true,
      },
      cilckId: null,
    };
  },
  async mounted() {
    await this.loadData();
    this.gantt();
  },
  watch: {
    isFullScreen: {
      handler() {
        this.fullScreen();
      },
    },
    isShowGrid: {
      handler(newVal) {
        gantt.config.show_grid = newVal;
        gantt.init(this.$refs.gantt);
      },
    },
  },
  methods: {
    initScales() {
      const { workTime } = { ...this.configData };
      if (workTime === "day") {
        gantt.config.scales = [
          { unit: "month", step: 1, format: "%Y年%M" },
          { unit: "day", step: 1, format: "%M%d日" },
        ];
      } else if (workTime === "hour") {
        gantt.config.scales = [
          { unit: "day", step: 1, format: "%Y年%n月%d日" },
          { unit: "hour", step: 1, format: "%h:00" },
        ];
      } else if (workTime === "week") {
        gantt.config.scales = [
          { unit: "year", step: 1, format: "%Y年" },
          { unit: "week", step: 1, format: "第%W周" },
        ];
      } else if (workTime === "month") {
        gantt.config.scales = [
          { unit: "year", step: 1, format: "%Y年" },
          { unit: "month", step: 1, format: "%n月" },
        ];
      } else {
        gantt.config.scales = [{ unit: "year", step: 1, format: "%Y年" }];
      }
    },
    fullScreen() {
      this.$emit("configArea", true);
      if (!gantt.getState().fullscreen) {
        gantt.expand();
      } else {
        gantt.collapse();
      }
    },
    time() {
      let tempTime = new Date();
      let year = tempTime.getFullYear();
      let month = tempTime.getMonth() + 1 < 10 ? "0" + (tempTime.getMonth() + 1) : tempTime.getMonth() + 1;
      let day = tempTime.getDate() < 10 ? "0" + tempTime.getDate() : tempTime.getDate();
      let hour = tempTime.getHours() < 10 ? "0" + tempTime.getHours() : tempTime.getHours();
      let minute = tempTime.getMinutes() < 10 ? "0" + tempTime.getMinutes() : tempTime.getMinutes();
      return `${year}-${month}-${day} ${hour}:${minute}`;
    },
    gantt() {
      let self = this;
      setTimeout(() => {
        gantt.plugins({
          tooltip: true,
          multiselect: true, // 激活多任务选择
          fullscreen: true,
          export_api: true,
          marker: true,
        });
        let today = new Date();
        let dateToStr = self.time();
        gantt.addMarker({
          start_date: today,
          css: "today",
          text: "今天",
          title: dateToStr,
        });
        const {
          rowHeight,
          isDragProgress,
          isDragLink,
          showLink,
          isDragMove,
          isDragSort,
          readonly,
          scaleHeight,
          scrollOffset,
        } = {
          ...this.configData,
        };
        gantt.config.show_grid = this.isShowGrid;
        gantt.config.columns = this.titlelist;
        // 顶部行高
        gantt.config.scale_height = scaleHeight;
        gantt.config.task_scroll_offset = scrollOffset;
        // 是否只读
        gantt.config.readonly = readonly;
        gantt.config.row_height = rowHeight;
        // 是否拖动任务进度
        gantt.config.drag_progress = isDragProgress;
        // 是否拖动以创建链接
        gantt.config.drag_links = isDragLink;
        gantt.config.show_links = showLink;
        // 是否可以拖动
        gantt.config.drag_move = isDragMove;
        gantt.config.order_branch = isDragSort ? "marker" : false;
        // 是否自动扩展时间
        gantt.config.fit_tasks = true;
        gantt.config.reorder_grid_columns = true;
        gantt.config.auto_types = true;
        // 定义日期对象转换
        gantt.config.xml_date = "%Y-%m-%d %H";
        this.initScales();

        gantt.config.show_empty_state = true;
        gantt.config.open_split_tasks = true;
        gantt.config.min_column_width = 80;
        gantt.config.duration_unit = "minute";
        gantt.config.details_on_create = true;
        gantt.i18n.setLocale("cn");

        // 模板
        gantt.templates.grid_row_class = function (start, end, task) {
          if (gantt.hasChild(task.id) != undefined) {
            return "grid_father_row";
          } else return "grid_row_class";
        };
        gantt.templates.grid_header_class = function () {
          return "grid_header_class";
        };
        gantt.templates.task_class = function (start, end, task) {
          if (task.type == "milestone" && task.shape) {
            return "milestone_shape_" + task.shape;
          }
          return "task_class task_class_normal";
        };

        gantt.templates.grid_indent = function () {
          return "<div class='gantt_tree_indent'></div>";
        };
        gantt.templates.rightside_text = function (start, end, task) {
          if (task.type == gantt.config.types.milestone) return task.text + " / ID: #" + task.id;
          return "";
        };
        gantt.templates.leftside_text = function (start, end, task) {
          if (task.type !== gantt.config.types.milestone) return task.progress.toFixed(2) * 100 + "%";
          return "";
        };

        gantt.templates.tooltip_text = function (start, end, task) {
          return (
            "<b>任务 :</b> " +
            task.text +
            "<br/><b>状态 :</b>" +
            task.state +
            "<br/><b>完成百分比 :</b>" +
            task.progress.toFixed(2) * 100 +
            "%" +
            "<br/><b>预计工期 :</b>" +
            task.workTime +
            "<br/><b>开始时间 :</b> " +
            gantt.templates.tooltip_date_format(start) +
            "<br/><b>结束时间 :</b> " +
            gantt.templates.tooltip_date_format(end)
          );
        };
        gantt.attachEvent("onTaskSelected", function (id) {
          const task = gantt.getTask(id);
          self.getTaskInfo(task);
        });
        // 获取任务拖动前事件进行校验
        gantt.attachEvent("onBeforeTaskDrag", function (id) {
          const task = gantt.getTask(id);
          if (task.state == "完成") {
            self.$message.warning("该任务已完成，禁止修改！");
            return false;
          } else return true;
        });
        // 获取任务拖动事件
        gantt.attachEvent("onAfterTaskDrag", function (id) {
          self.updateTaskTime(id);
        });
        // 捕获垂直移动任务事件
        let timer = null;
        gantt.attachEvent("onAfterTaskMove", function (id, parent) {
          clearTimeout(timer);
          timer = setTimeout(() => {
            const childrenIds = gantt.getChildren(parent);
            let forms = [];
            childrenIds.forEach((item) => {
              let obj = { id: item * 1 };
              forms.push(obj);
            });
            self.setTaskOrder(forms);
          }, 500);
        });
        // 捕获link创建事件
        gantt.attachEvent("onBeforeLinkAdd", function (id, link) {
          self.setLinkAdd(link);
        });
        // link被删除的事件
        gantt.attachEvent("onAfterLinkDelete", function (id, item) {
          self.deleteLink(item);
        });

        gantt.attachEvent("onTaskDblClick", function (id) {
          console.log(id);
          // self.isConfigArea = false
        });

        gantt.attachEvent("onTaskCreated", function (task) {
          let newTask = {};
          let day = new Date();
          newTask.parentTaskId = task.parent;
          newTask.title = "新增任务";
          newTask.text = "新增任务";
          newTask.start_date = task.start_date;
          newTask.planBegin = task.start_date;
          newTask.planEnd = new Date(day.setDate(day.getDate() + 1));

          self.addOrUpdate(newTask).then(() => {
            self.refresh().then(() => {
              gantt.selectTask(self.cilckId);
              let info = gantt.getTask(self.cilckId);
              self.openTaskInfo(info);
            });
          });
          return false;
        });

        gantt.init(this.$refs.gantt);
        gantt.parse(this.tasks);
      }, 200);
    },
    openTaskInfo(info) {
      this.taskInfoDate = info;
      this.isConfigArea = false;
    },
    closeInfo() {
      this.isConfigArea = true;
    },
    updateGantt(newVal) {
      const {
        rowHeight,
        isDragProgress,
        isDragLink,
        showLink,
        isDragMove,
        isDragSort,
        readonly,
        scaleHeight,
        scrollOffset,
        blockBorderColor,
      } = {
        ...newVal,
      };
      // const dom = document.getElementsByClassName('task_class')
      // dom[0].style.setProperty('background-color', blockBorderColor)
      // dom[0].forEach((item, index) => {
      //   item[index].style.setProperty('background-color', blockBorderColor)
      // })
      console.log(blockBorderColor);
      gantt.config.scale_height = scaleHeight;
      // 是否只读
      gantt.config.task_scroll_offset = scrollOffset;
      gantt.config.readonly = readonly;
      gantt.config.row_height = rowHeight;
      // 是否拖动任务进度
      gantt.config.drag_progress = isDragProgress;
      // 是否拖动以创建链接
      gantt.config.drag_links = isDragLink;
      gantt.config.show_links = showLink;
      // 是否可以拖动
      gantt.config.drag_move = isDragMove;
      gantt.config.order_branch = isDragSort ? "marker" : false;
      this.initScales();
      gantt.init(this.$refs.gantt);
    },
    refreshTask(newVal) {
      let task = gantt.getTask(newVal.id);
      task = newVal;
      task.start_date = new Date(Date.parse(newVal.planBegin));
      task.end_date = new Date(Date.parse(newVal.planEnd));
      this.addOrUpdate(task);
      gantt.refreshTask(newVal.id);
      gantt.init(this.$refs.gantt);
    },
    getTaskInfo(taskInfo) {
      this.taskInfoDate = taskInfo;
    },
    // 保存子任务执行顺序
    setTaskOrder(childrenIds) {
      this.$server()
        .erdfRequest(`/server/${this.microservices}/base/${this.resource}/updateTaskSort`, [childrenIds], "POST")
        .then(() => {
          // this.$message('调整成功', 'success')
        })
        .catch((response) => {
          console.log(response);
          // this.$message(response.data.message, 'error')
        });
    },
    // 保存Link
    setLinkAdd(link) {
      this.$server()
        .erdfRequest(`/server/${this.microservices}/base/TaskLink/insert`, link, "POST")
        .then(() => {
          this.$message.success("添加成功");
        })
        .catch((response) => {
          console.log(response);
          // this.$message(response.data.message, 'error')
        });
    },
    // 删除Link
    deleteLink(item) {
      this.$server()
        .erdfRequest(`/server/${this.microservices}/base/TaskLink/deletesPhysical`, [item], "POST")
        .then(() => {
          this.$message.success("删除成功");
        })
        .catch((response) => {
          console.log(response);
          // this.$message(response.data.message, 'error')
        });
    },
    // 修改任务时间、进度等
    updateTaskTime(id) {
      const data = gantt.getTask(id);
      data.planBegin = data.start_date;
      data.planEnd = data.end_date;
      data.point = data.progress.toFixed(2) * 100;
      this.$server()
        .erdfRequest(`/server/${this.microservices}/base/${this.resource}/updateFull`, data, "POST")
        .then(() => {
          this.$message.success("修改成功");
        })
        .catch((response) => {
          console.log(response);
          // this.$message(response.data.message, 'error')
        });
    },
    // 打开任务编辑界面
    openTaskDetail(id) {
      this.$router.push({
        path: "/baseData/taskManage/detail",
        query: { taskInfoId: id ? id : null, operate: "edit" },
      });
    },
    async refresh(params) {
      await this.loadData(params);
      gantt.clearAll();
      gantt.init(this.$refs.gantt);
      gantt.parse(this.tasks);
    },
    async loadData(params) {
      let self = this;
      await self
        .$server()
        .erdfRequest(
          `/server/${self.microservices}/base/${self.resource}/getTaskTree`,
          params ? [params, null, null] : [this.ganttCondition, null, null],
          "post"
        )
        .then(async function (res) {
          let list = [];
          let ids = [];
          res.forEach((eae) => {
            eae.progress = eae.point / 100;
            eae.duration = eae.workTime;
            eae.text = eae.title;
            eae.$open = true;
            eae.start_date = eae.planBegin;
            eae.end_date = eae.planEnd;
            if (eae.children != []) {
              eae.render = "split";
            }
            ids.push(eae.id);
            list.push(eae);
          });
          await self
            .$server()
            .erdfRequest(`/server/${self.microservices}/base/TaskLink/selectTaskLinksByIds`, [ids], "post")
            .then((res) => {
              self.tasks.data = list;
              self.tasks.links = res;
            });
        })
        .catch(function (response) {
          self.$message.error(response.data.message);
        });
    },
    exportFile() {
      // gantt.exportToExcel({
      //   name: 'gantt.xlsx',
      //   date_format: 'yyyy-yy-mm'
      // })
      // 目前官方8.0版本未支持导出
      // gantt.exportToPDF()
      gantt.exportToPNG({
        header: '<link rel="stylesheet" href="http://docs.dhtmlx.com/gantt/samples/common/customstyles.css?v=8.0.3">',
      });
    },
    getLastSelectedTask() {
      let ids = gantt.getSelectedTasks();
      ids = ids.map(Number);
      return ids;
    },
    async addOrUpdate(obj) {
      let isUpdate = false;
      let self = this;
      if (obj.id && obj.id != "") {
        isUpdate = true;
      } else {
        obj.busSource = this.busSource;
      }
      await self
        .$server()
        .addOrUpdate(self.microservices, self.resource, obj, isUpdate, 1)
        .then((res) => {
          this.cilckId = res;
          this.$message.success("成功");
          return res;
        })
        .catch((err) => {
          console.log(err);
        });
    },
  },
};
</script>
  
<style lang="scss">
$blockBorderColor: #e48e0d;

.new-page {
  margin: 5px 0px;
  background-color: #fff;
}

.gantt_task .gantt_task_scale .gantt_scale_cell {
  font-weight: bold;
  font-size: 14px;
  color: rgba(0, 0, 21, 0.7);
}
.grid_header_class {
  font-weight: bold;
  font-size: 14px;
  color: rgba(0, 0, 21, 0.7) !important;
}

.grid_row_class {
  font-weight: 500;
  color: rgba(0, 0, 0, 0.7);
}
.gantt_grid :hover {
  background-color: #e1e1e1ea !important;
}

.task_class {
  border-radius: 15px !important;
  font-size: 15px;
  margin-top: 6px;
  height: 24px !important;
  line-height: 24px !important;
}

.task_class_normal {
  background-color: #4876ff7d;
  border: 1px solid rgba(48, 153, 239, 0.791);
}
.gantt_task_progress {
  background: #4876ff !important;
}
.gantt_task_row.gantt_selected .gantt_task_cell {
  background-color: #e1e1e1ea;
  border-right-color: #e0e0dfd2;
}
.gantt_grid_data .gantt_row.gantt_selected,
.gantt_grid_data .gantt_row.odd.gantt_selected,
.gantt_task_row.gantt_selected {
  background-color: #e1e1e1ea;
}
.gantt_task_content {
  color: #f9f7f7 !important;
  font-weight: 500;
}
.task_level {
  color: $blockBorderColor;
}
.gantt_line_wrapper div {
  background-color: #55554eec;
}
.gantt_link_arrow_right {
  border-left-color: #55554eec;
}
.gantt_task_link:hover .gantt_line_wrapper div {
  box-shadow: 0 5px 5px 0 #bbbaba;
}
.gantt_task_line.gantt_project {
  background-color: #0cd258 !important;
  // border: 1px solid #1bc75d !important;
}
.gantt_task_line.gantt_project.gantt_selected,
.gantt_task_line.gantt_selected {
  box-shadow: 0 0 1px #1372d9;
}
.gantt_marker {
  background-color: rgb(23 108 236 / 40%);
}
.grid_father_row {
  font-weight: 600;
}
::-webkit-scrollbar {
  width: 18px;
  height: 18px;
}
::-webkit-scrollbar-thumb {
  /*滚动条里面小方块*/
  border-radius: 12px;
  border: 5px solid rgba(255, 255, 255, 1);
  background: lightgray;
}
.level {
  font-weight: 600;
}
.level-danger {
  color: #ec3535;
}

.level-warning {
  color: #f2c604;
}

.level-primary {
  color: #3e8ef8;
}

.level-success {
  color: #66d533;
}
.tabClass {
  font-size: 16px;
  font-weight: 500;
}
.milestone_shape_4 .gantt_task_content {
  background: unset !important;
  transform: unset !important;
  border-left: 15px solid transparent !important;
  border-right: 15px solid transparent !important;
  border-bottom: 20px solid #d33db0 !important;
}
</style>
  